package bitmap
{
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.utils.ByteArray;
	import flash.utils.getTimer;
	
	/**
	 * 用固定的N个loader进行异步的decode，效率较高
	 * 异步操作对于bitmap的处理上并不会增加复杂性。
	 * @author Ryan
	 * 
	 */	
	public class ImageDecoder
	{
		private static var MAX_LOADER:int = 2;
		private var _loaderPool :Vector.<ImgLoader>;
		private var _waitList :Vector.<Object>;
		private var _lastGetTime:Number;
		
		public function ImageDecoder() {
			_loaderPool = new Vector.<ImgLoader>;
			// 初始化5个loader进行decode
			for( var i:int = 0;i< MAX_LOADER;i++){
				_loaderPool.push( new ImgLoader() );
			}
			_waitList =new Vector.<Object>;
		}
		
		/**
		 * 异步的解码，完成后填入bitmapData中 
		 * 对于bitmap的处理，可以不用等待，直接使用。
		 * 这个函数有时候很慢（>6ms)
		 * @param data
		 * @param bitmapData
		 * 
		 */		
		public function decode( data : ByteArray, bitmap :Bitmap,callBack:Function = null) : void {
			var s:Number = getTimer();
			var decoder : ImgLoader = getFreeLoader();
			// 如果没有空闲的loader，加入等待。
			if( !decoder ){
				var info:ImgInfo = new ImgInfo();
				info.data = data;
				info.bitmap = bitmap;
				info.callBack = callBack;
				_waitList.push( info );
				return;
			}
			decoder.bitmap = bitmap;
			decoder.callBack = callBack;
        	decoder.contentLoaderInfo.addEventListener(Event.COMPLETE,handler);
        	decoder.loadBytes( data );
			if(getTimer() - s)trace( "Decode Img:",getTimer() - s );
		}
		
		// 这里存在泄漏，有可能handler不被调到。
		private function handler(event:Event):void{
			var decoder:ImgLoader = event.currentTarget.loader as ImgLoader;
			decoder.contentLoaderInfo.removeEventListener(Event.COMPLETE,handler);
			decoder.bitmap.bitmapData = (decoder.content as Bitmap).bitmapData;
			if( decoder.callBack!= null ){
				decoder.callBack( decoder.bitmap.bitmapData );
			}
			
			decoder.unload();
			// 如果有等待，继续解码等待列表中的图片
			_loaderPool.push( decoder );
			if( _waitList.length > 0 ){
				var obj : ImgInfo = _waitList.pop();
				decode( obj.data, obj.bitmap, obj.callBack );
			}
		}
		
		private function getFreeLoader() : ImgLoader {
			var now:Number = new Date().getTime();
			if( _loaderPool.length > 0 ){
				_lastGetTime = now;
				return _loaderPool.pop();
			} else {
				if( now - _lastGetTime > 5000 ){
					_lastGetTime = now;
					return new ImgLoader();
				}
			}
			return null;
		}
		
	}
}
import flash.display.Bitmap;
import flash.display.Loader;
import flash.utils.ByteArray;

class ImgLoader extends Loader{
	public var bitmap:Bitmap;
	public var callBack:Function;
}

class ImgInfo {
	public var bitmap:Bitmap;
	public var callBack:Function;
	public var data:ByteArray;
}